#generate db schema

import os, sys
from db_schema import *
import jinja2
import types
import time

SRC_PATH = './template/db/'
OUTPUT_PATH = '../db/obj/'
OUTPUT_ORM_PATH = '../db/'
SRC_SUFFIX = '.py'

sys.path.append(SRC_PATH)


g_db_desc = {}

#describe a data object's db structure
class SchemaObj:
	def __init__(self, fname, name, key=''):
		self.key = key
		self.name = name
		self.index = ''
		self.key_list = []
		self.fname = fname
	
	def set_data(self, data_def, key_list):
		self.data = data_def 	
		self.key_list = key_list
	
	def set_index(self, idx):
		self.index = idx

	def db_create_cmd(self):
		msg = 'CREATE TABLE IF NOT EXIST `%s` (' % self.name
		msg += '`_id` int primary key auto_increment,'
		msg += '`_uptime TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,`'

		for k, v in self.data.items():
			if v['type'] != INT and v['type'] != STR: continue
		
			msg += '`%s` %s' % (k, v['ftype'])
			if k == self.key:
				msg += ' NOT NULL UNIQUE_KEY ' 
			df = '0'
			if v['type'] == STR:
				df = '\'\''
				
			msg += ' DEFAULT %s,' % df	
	
		if len(self.index) > 0:
			msg += 'INDEX _ind(%s)' % self.index		
	
		msg += ') ENGINE=InnoDB' 
		return msg
	
	def db_update_cmd(self, kval='', kname=''):
		pass

	def gen_delete_cmd(self):
		pass

#get all valid template file in SRC_PATH
def get_all_file():
	filelist = os.listdir(SRC_PATH)
	ret = []
	for f in filelist:
		name = f.split(SRC_SUFFIX)
		if len(name) > 1:
			ret += [ name[0], ]
		else:
			pass

	return ret

def error_msg(fname, pname, msg):
	print 'ERROR: %s: object_def: %s . %s' % (fname, pname, msg)

#gen db structure
def gen_db_struct(fname, obj_name, desc):
	global g_db_desc
	vdata = {}
	key_list = []
	key = desc.get('key', '')
	pobj = SchemaObj(fname, obj_name, key)
	#check validate

	for k,v in desc.iteritems():
		p = {}
		if type(v) == types.ListType:
			vtype = v[0]
		else:
			vtype = v	

		if vtype == INT:
			p['ftype'] = 'int'
			key_list.append(k)
		elif vtype == STR:
			if type(v) == types.ListType and len(v) >= 2:
				p['ftype'] = 'varchar(%d)' % v[1] 
			else:
				p['ftype'] = 'varchar(256)'

			key_list.append(k)
		
		p['type'] = vtype
		vdata[k] = p

	#set index if exist	
	idx = desc.get('index', None)
	if idx:
		if len(idx) > 1:	
			error_msg(fname, obj_name, 'index can be only designed for one field')
		pobj.set_index(index)
	
	pobj.set_data(vdata, key_list)
	g_db_desc[obj_name] = pobj


def output_schema():
	fileloader = jinja2.FileSystemLoader('./template/')
	jinja_env = jinja2.Environment(loader = fileloader)
	tp = jinja_env.get_template('db_desc.tmpl')
	target = OUTPUT_ORM_PATH + 'db_desc.py'
	mp = {} 
	for k,v in g_db_desc.items():
		mp[k] = {}
		mp[k]['field'] = str(v.key_list)
		s = ''
		for f, attr in v.data.items():
			s += '\'' + f + '\':\'' + attr['ftype'] + '\', ' 

		mp[k]['attr'] = s 

		s = ''
		i = 0
		cmsg = v.db_create_cmd().split(',')
		for msg in cmsg:
			if i > 0:
				s += '\t\t'
			s += '\'' + msg + ',' + '\'\n'
			i = i + 1

		mp[k]['create_msg'] = s

	tp.stream(dbs=mp,date=time.ctime()).dump(target)	
	print 'generate ok......'
	pass
	
def generate_db(fname):
	m = __import__(fname)
	for pname, desc in m.__dict__.iteritems():
		if not type(desc) == types.DictType:
			continue
		if len(pname) > 2 and pname[:2] == "__":
			continue

		if not desc.has_key('data'):
			print error_msg(fname, pname, 'no data define')
			continue
		
		gen_db_struct(fname, pname, desc['data'])
	
	output_schema()
	

	
if __name__ == '__main__':
	all_file = get_all_file()
	for f in all_file:
		generate_db(f)
